#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
对话管理器
处理客户对话的上下文和状态管理
"""

import json
import logging
import threading
import time
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Tuple
from dataclasses import dataclass, asdict

from config.prompts import TaskType, PromptConfig

logger = logging.getLogger(__name__)

@dataclass
class ConversationItem:
    """对话项"""
    message: str
    sender: str  # "customer" 或 "ai"
    timestamp: datetime
    task_type: Optional[TaskType] = None
    summary: Optional[str] = None

@dataclass
class ConversationSession:
    """对话会话"""
    session_id: str
    customer_id: str
    start_time: datetime
    last_activity: datetime
    conversation_items: List[ConversationItem]
    current_task: Optional[TaskType] = None
    order_info: Optional[Dict] = None
    # 新增会话状态管理
    is_human_service: bool = False  # 是否正在人工服务
    human_service_start: Optional[datetime] = None  # 人工服务开始时间
    auto_switch_back_time: Optional[datetime] = None  # 自动转回AI的时间
    last_communication_time: Optional[datetime] = None  # 最后沟通时间（用于30秒无沟通检测）

class ConversationManager:
    """对话管理器"""
    
    _instance = None
    _initialized = False
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance
    
    def __init__(self):
        """初始化对话管理器（单例模式）"""
        if not ConversationManager._initialized:
            self.sessions: Dict[str, ConversationSession] = {}
            self.context_window = timedelta(minutes=PromptConfig.CONTEXT_WINDOW_MINUTES)
            
            # 启动定时检查线程
            self.check_thread = threading.Thread(target=self.run_auto_switch_check, daemon=True)
            self.check_thread.start()
            logger.info("🔄 30秒无沟通自动转回AI检查线程已启动")
            
            ConversationManager._initialized = True
    
    def get_or_create_session(self, customer_id: str) -> ConversationSession:
        """
        获取或创建对话会话
        
        Args:
            customer_id: 客户ID
            
        Returns:
            ConversationSession: 对话会话
        """
        session_id = f"session_{customer_id}"
        
        if session_id not in self.sessions:
            # 创建新会话
            session = ConversationSession(
                session_id=session_id,
                customer_id=customer_id,
                start_time=datetime.now(),
                last_activity=datetime.now(),
                conversation_items=[],
                current_task=None,
                order_info=None
            )
            self.sessions[session_id] = session
            logger.info(f"创建新对话会话: {session_id}")
        else:
            # 更新最后活动时间
            self.sessions[session_id].last_activity = datetime.now()
        
        return self.sessions[session_id]
    
    def add_customer_message(self, customer_id: str, message: str) -> ConversationSession:
        """
        添加客户消息
        
        Args:
            customer_id: 客户ID
            message: 客户消息
            
        Returns:
            ConversationSession: 更新后的会话
        """
        session = self.get_or_create_session(customer_id)
        
        # 识别任务类型
        task_type = PromptConfig.get_task_type(message)
        
        # 创建对话项
        conversation_item = ConversationItem(
            message=message,
            sender="customer",
            timestamp=datetime.now(),
            task_type=task_type
        )
        
        # 添加到会话
        session.conversation_items.append(conversation_item)
        session.current_task = task_type
        session.last_activity = datetime.now()
        
        # 更新沟通时间（如果正在人工服务）
        if session.is_human_service:
            session.last_communication_time = datetime.now()
            logger.info(f"💬 客户 {customer_id} 发送消息，更新沟通时间")
        
        logger.info(f"添加客户消息: {message[:50]}... (任务类型: {task_type.value})")
        
        return session
    
    def add_ai_response(self, customer_id: str, response: str, task_type: Optional[str] = None) -> ConversationSession:
        """
        添加AI回复
        
        Args:
            customer_id: 客户ID
            response: AI回复
            task_type: 任务类型（字符串或TaskType枚举）
            
        Returns:
            ConversationSession: 更新后的会话
        """
        session = self.get_or_create_session(customer_id)
        
        # 处理任务类型
        if isinstance(task_type, str):
            # 如果是字符串，尝试转换为TaskType枚举
            try:
                if task_type == "查询商品信息":
                    task_type_enum = TaskType.QUERY_PRODUCT
                elif task_type == "下单":
                    task_type_enum = TaskType.PLACE_ORDER
                elif task_type == "呼叫客服":
                    task_type_enum = TaskType.CALL_HUMAN
                else:
                    task_type_enum = None
            except:
                task_type_enum = None
        else:
            task_type_enum = task_type
        
        # 创建对话项
        conversation_item = ConversationItem(
            message=response,
            sender="ai",
            timestamp=datetime.now(),
            task_type=task_type_enum
        )
        
        # 添加到会话
        session.conversation_items.append(conversation_item)
        session.last_activity = datetime.now()
        
        # 更新沟通时间（如果正在人工服务）
        if session.is_human_service:
            session.last_communication_time = datetime.now()
            logger.info(f"🤖 AI回复客户 {customer_id}，更新沟通时间")
        
        logger.info(f"添加AI回复: {response[:50]}...")
        
        return session
    
    def get_relevant_history(self, customer_id: str) -> List[Dict]:
        """
        获取相关的对话历史
        
        Args:
            customer_id: 客户ID
            
        Returns:
            List[Dict]: 对话历史列表
        """
        session = self.get_or_create_session(customer_id)
        
        # 过滤时间窗口内的对话
        cutoff_time = datetime.now() - self.context_window
        relevant_items = [
            item for item in session.conversation_items
            if item.timestamp >= cutoff_time
        ]
        
        # 转换为字典格式
        history = []
        for item in relevant_items:
            history.append({
                "type": item.sender,
                "message": item.message,
                "timestamp": item.timestamp.isoformat(),
                "task_type": item.task_type.value if item.task_type else None
            })
        
        return history
    
    def generate_conversation_summary(self, customer_id: str) -> List[str]:
        """
        生成对话摘要
        
        Args:
            customer_id: 客户ID
            
        Returns:
            List[str]: 对话摘要列表
        """
        session = self.get_or_create_session(customer_id)
        summary = []
        
        # 分析对话内容，生成摘要
        for item in session.conversation_items[-PromptConfig.MAX_CONVERSATION_SUMMARY:]:
            if item.sender == "customer":
                if item.task_type == TaskType.QUERY_PRODUCT:
                    summary.append(f"客户在咨询：{item.message}")
                elif item.task_type == TaskType.PLACE_ORDER:
                    # 提取数量信息
                    if any(word in item.message for word in ["件", "个", "套", "箱", "包", "盒"]):
                        summary.append(f"客户要下单{item.message}")
                    else:
                        summary.append(f"客户要下单：{item.message}")
                elif item.task_type == TaskType.CALL_HUMAN:
                    summary.append(f"客户要求人工客服：{item.message}")
        
        return summary
    
    def update_order_info(self, customer_id: str, order_info: Dict) -> None:
        """
        更新订单信息
        
        Args:
            customer_id: 客户ID
            order_info: 订单信息
        """
        session = self.get_or_create_session(customer_id)
        session.order_info = order_info
        logger.info(f"更新订单信息: {order_info}")
    
    def get_order_info(self, customer_id: str) -> Optional[Dict]:
        """
        获取订单信息
        
        Args:
            customer_id: 客户ID
            
        Returns:
            Optional[Dict]: 订单信息
        """
        session = self.get_or_create_session(customer_id)
        return session.order_info
    
    def clear_session(self, customer_id: str) -> None:
        """
        清除会话
        
        Args:
            customer_id: 客户ID
        """
        session_id = f"session_{customer_id}"
        if session_id in self.sessions:
            del self.sessions[session_id]
            logger.info(f"清除会话: {session_id}")
    
    def cleanup_expired_sessions(self) -> None:
        """清理过期的会话"""
        current_time = datetime.now()
        expired_sessions = []
        
        for session_id, session in self.sessions.items():
            if current_time - session.last_activity > timedelta(hours=24):
                expired_sessions.append(session_id)
        
        for session_id in expired_sessions:
            del self.sessions[session_id]
            logger.info(f"清理过期会话: {session_id}")
    
    def get_session_stats(self) -> Dict:
        """
        获取会话统计信息
        
        Returns:
            Dict: 统计信息
        """
        total_sessions = len(self.sessions)
        active_sessions = len([
            s for s in self.sessions.values()
            if datetime.now() - s.last_activity <= timedelta(hours=1)
        ])
        
        return {
            "total_sessions": total_sessions,
            "active_sessions": active_sessions,
            "context_window_minutes": PromptConfig.CONTEXT_WINDOW_MINUTES
        } 

    def switch_to_human_service(self, customer_id: str, auto_switch_minutes: int = 5) -> ConversationSession:
        """
        将会话切换到人工服务
        
        Args:
            customer_id: 客户ID
            auto_switch_minutes: 自动转回AI的分钟数（默认5分钟，便于测试）
            
        Returns:
            ConversationSession: 更新后的会话
        """
        session = self.get_or_create_session(customer_id)
        session.is_human_service = True
        session.human_service_start = datetime.now()
        # 设置自动转回AI的时间
        session.auto_switch_back_time = datetime.now() + timedelta(minutes=auto_switch_minutes)
        # 设置初始沟通时间
        session.last_communication_time = datetime.now()
        
        logger.info(f"🔄 客户 {customer_id} 已切换到人工服务，30秒无沟通将自动转回AI")
        return session
    
    def switch_back_to_ai(self, customer_id: str) -> ConversationSession:
        """
        将会话切换回AI服务
        
        Args:
            customer_id: 客户ID
            
        Returns:
            ConversationSession: 更新后的会话
        """
        session = self.get_or_create_session(customer_id)
        session.is_human_service = False
        # 保留人工服务开始时间用于判断是否刚转回AI
        # session.human_service_start = None  # 注释掉，保留时间用于判断
        session.auto_switch_back_time = None
        session.last_communication_time = None  # 清理沟通时间
        
        logger.info(f"🤖 客户 {customer_id} 已切换回AI服务")
        return session
    
    def should_switch_back_to_ai(self, customer_id: str) -> bool:
        """
        检查是否应该自动转回AI服务
        
        Args:
            customer_id: 客户ID
            
        Returns:
            bool: 是否应该转回AI
        """
        session = self.get_or_create_session(customer_id)
        
        # 如果不在人工服务状态，直接返回False
        if not session.is_human_service:
            return False
        
        current_time = datetime.now()
        
        # 检查30秒无沟通的情况 - 增加更严格的判断
        if session.last_communication_time:
            time_since_last_communication = current_time - session.last_communication_time
            # 只有当超过30秒且人工服务时间超过1分钟时才自动转回
            if time_since_last_communication.total_seconds() >= 30:
                # 检查人工服务是否已经持续了足够长的时间（至少1分钟）
                if session.human_service_start:
                    human_service_duration = current_time - session.human_service_start
                    if human_service_duration.total_seconds() >= 60:  # 至少1分钟
                        logger.info(f"⏰ 客户 {customer_id} 30秒无沟通且人工服务超过1分钟，自动转回AI")
                        return True
                    else:
                        logger.info(f"⏰ 客户 {customer_id} 30秒无沟通但人工服务时间不足1分钟，继续人工服务")
                        return False
                else:
                    # 如果没有人工服务开始时间，使用默认逻辑
                    logger.info(f"⏰ 客户 {customer_id} 30秒无沟通，自动转回AI")
                    return True
        
        # 检查是否超过自动转回时间（原有的分钟级超时机制）
        if session.auto_switch_back_time and current_time >= session.auto_switch_back_time:
            logger.info(f"⏰ 客户 {customer_id} 人工服务超时，自动转回AI")
            return True
        
        # 检查是否是新的一天（跨天自动转回AI）
        if session.human_service_start:
            days_diff = (current_time - session.human_service_start).days
            if days_diff >= 1:
                logger.info(f"📅 客户 {customer_id} 跨天会话，自动转回AI")
                return True
        
        return False
    
    def check_and_auto_switch(self, customer_id: str) -> bool:
        """
        检查并自动切换会话状态
        
        Args:
            customer_id: 客户ID
            
        Returns:
            bool: 是否发生了切换
        """
        if self.should_switch_back_to_ai(customer_id):
            self.switch_back_to_ai(customer_id)
            return True
        return False
    
    def is_currently_human_service(self, customer_id: str) -> bool:
        """
        检查当前是否在人工服务状态
        
        Args:
            customer_id: 客户ID
            
        Returns:
            bool: 是否在人工服务状态
        """
        session = self.get_or_create_session(customer_id)
        return session.is_human_service 

    def check_all_sessions_auto_switch(self) -> List[str]:
        """
        检查所有会话的自动转回状态
        
        Returns:
            List[str]: 已转回AI的客户ID列表
        """
        switched_customers = []
        
        for session_id, session in self.sessions.items():
            customer_id = session.customer_id
            
            # 检查是否应该自动转回AI
            if self.should_switch_back_to_ai(customer_id):
                logger.info(f"⏰ 定时检查：客户 {customer_id} 人工服务超时，自动转回AI")
                self.switch_back_to_ai(customer_id)
                switched_customers.append(customer_id)
        
        if switched_customers:
            logger.info(f"🔄 定时检查完成，已转回 {len(switched_customers)} 个客户到AI服务")
        
        return switched_customers
    
    def update_communication_time(self, customer_id: str) -> None:
        """
        手动更新沟通时间（用于客服回复时）
        
        Args:
            customer_id: 客户ID
        """
        session = self.get_or_create_session(customer_id)
        if session.is_human_service:
            session.last_communication_time = datetime.now()
            logger.info(f"💬 更新客户 {customer_id} 的沟通时间")
    
    def get_session_info(self, customer_id: str) -> Dict:
        """
        获取会话详细信息
        
        Args:
            customer_id: 客户ID
            
        Returns:
            Dict: 会话信息
        """
        session = self.get_or_create_session(customer_id)
        
        current_time = datetime.now()
        time_until_switch = None
        time_since_last_communication = None
        
        if session.auto_switch_back_time:
            time_until_switch = (session.auto_switch_back_time - current_time).total_seconds()
        
        if session.last_communication_time:
            time_since_last_communication = (current_time - session.last_communication_time).total_seconds()
        
        return {
            'customer_id': customer_id,
            'is_human_service': session.is_human_service,
            'human_service_start': session.human_service_start.isoformat() if session.human_service_start else None,
            'auto_switch_back_time': session.auto_switch_back_time.isoformat() if session.auto_switch_back_time else None,
            'last_communication_time': session.last_communication_time.isoformat() if session.last_communication_time else None,
            'last_activity': session.last_activity.isoformat(),
            'conversation_count': len(session.conversation_items),
            'current_time': current_time.isoformat(),
            'time_until_switch': time_until_switch,
            'time_since_last_communication': time_since_last_communication,
            'should_switch_back': self.should_switch_back_to_ai(customer_id)
        } 

    def run_auto_switch_check(self) -> None:
        """
        定时检查所有会话的自动转回状态
        """
        logger.info("🔄 启动30秒无沟通自动转回AI检查线程")
        while True:
            try:
                # 检查所有会话的自动转回状态
                switched_customers = self.check_all_sessions_auto_switch()
                if switched_customers:
                    logger.info(f"⏰ 定时检查完成，已转回 {len(switched_customers)} 个客户到AI服务: {switched_customers}")
                
                # 等待指定间隔
                time.sleep(PromptConfig.AUTO_SWITCH_CHECK_INTERVAL_SECONDS)
            except Exception as e:
                logger.error(f"❌ 定时检查异常: {str(e)}")
                time.sleep(PromptConfig.AUTO_SWITCH_CHECK_INTERVAL_SECONDS) 